#pragma once

#include "doc/convert/attribute_convert/attribute_convertor.h"

namespace hawking {
namespace indexlib {

/*
    memory layout:
    | T |
*/
template <typename T>
class SingleValueAttributeConvertor : public AttributeConvertor
{
public:
    SingleValueAttributeConvertor(util::ColumnType column_type) :
        AttributeConvertor(column_type) {}
    virtual ~SingleValueAttributeConvertor() = default;

protected:
    // direct value
    virtual std::string_view InnerEncode_(
        const util::FieldValue* field_value, Pool* pool) override {
        T* value = (T*)Allocate_(pool, sizeof(T));
        switch (column_type_)
        {
        case util::COLUMN_INT8:
        case util::COLUMN_INT16:
        case util::COLUMN_INT32:
        case util::COLUMN_INT64:
            *value = static_cast<T>(field_value->int_value());
            break;
        case util::COLUMN_FLOAT:
        case util::COLUMN_DOUBLE:
            *value = static_cast<T>(field_value->double_value());
        default:
            break;
        }
        return std::string_view((char*)value, sizeof(T));
    }

    virtual void InnerDecode_(
        const uint8_t* data_addr, util::FieldValue* value) override {
        switch (column_type_) {
        case util::ColumnType::COLUMN_INT8: {
            value->set_int_value(*data_addr);
            break;
        }
        case util::ColumnType::COLUMN_INT16: {
            value->set_int_value(*(reinterpret_cast<uint16_t*>(data_addr)));
            break;
        }
        case util::ColumnType::COLUMN_INT32: {
            value->set_int_value(*(reinterpret_cast<uint32_t*>(data_addr)));
            break;
        }
        case util::ColumnType::COLUMN_INT64: {
            value->set_int_value(*(reinterpret_cast<uint64_t*>(data_addr)));
            break;
        }
        case util::ColumnType::COLUMN_FLOAT: {
            value->set_double_value(*(reinterpret_cast<float*>(data_addr)));
            break;
        }
        case util::ColumnType::COLUMN_DOUBLE: {
            value->set_double_value(*(reinterpret_cast<double*>(data_addr)));
            break;
        }
        default: {
            LOG(ERROR) << "Un single value, column_type_ "
                << static_cast<int32_t>(column_type_);
        }
    }
};

}
}